﻿/*
 * eID Applet Project.
 * Copyright (C) 2009 FedICT.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, see 
 * http://www.gnu.org/licenses/.
 */

using System;
using System.Web;
using System.Web.SessionState;
using System.Web.Configuration;
using System.IO;
using System.Text;
using System.Reflection;

namespace Codinfinity.BeIDApplet
{

    public class AppletService : IHttpHandler, IRequiresSessionState
    {

        public AppletService()
        {
        }


        public void ProcessRequest(HttpContext httpContext)
        {
            HttpRequest httpRequest = httpContext.Request;
            HttpResponse httpResponse = httpContext.Response;
            try
            {
                
                if ("GET".Equals(httpRequest.HttpMethod))
                {
                    httpResponse.Write("<html><body>The eID Applet Service should not be invoked directly.</body></html>");
                    return;
                }
                if (!"POST".Equals(httpRequest.HttpMethod))
                {
                    httpResponse.StatusCode = 400; // bad request
                    return;
                }
                String protocolVersion = httpRequest.Headers["X-AppletProtocol-Version"];
                if (!"1".Equals(protocolVersion))
                {
                    httpResponse.StatusCode = 400; // bad request
                    return;
                }
                String messageType = httpRequest.Headers["X-AppletProtocol-Type"];
                if ("HelloMessage".Equals(messageType))
                {
                    httpResponse.AddHeader("X-AppletProtocol-IncludeAddress", "true");
                    httpResponse.AddHeader("X-AppletProtocol-IncludePhoto", "true");
                    httpResponse.AddHeader("X-AppletProtocol-PreLogoff", "true");
                    sendCommand("IdentificationRequestMessage", httpResponse);
                    return;
                }
                else if ("IdentityDataMessage".Equals(messageType))
                {
                    int identityFileSize = int.Parse(httpRequest.Headers["X-AppletProtocol-IdentityFileSize"]);
                    Stream stream = httpRequest.InputStream;
                    byte[] identityFile = new byte[identityFileSize];
                    stream.Read(identityFile, 0, identityFileSize);

                    int idx = 0;
                    
                    while (idx < identityFileSize-1)
                    {
                        int tag = identityFile[idx++];
                        int length = identityFile[idx++];
                        byte[] buffer = new byte[length];
                        Array.Copy(identityFile, idx, buffer, 0, length);
                        idx += length;
                        switch (tag)
                        {
                            case 5: 
                                Identity.Locality = Encoding.UTF8.GetString(buffer);
                                break;
                            case 6:
                                Identity.NationalNumber = Encoding.UTF8.GetString(buffer);
                                break;
                            case 7:
                                Identity.LastName = Encoding.UTF8.GetString(buffer);
                                break;
                            case 8:
                                Identity.FirstName = Encoding.UTF8.GetString(buffer);
                                break;
                            case 10:
                                Identity.Nationality = Encoding.UTF8.GetString(buffer);
                                break;
                            case 11:
                                Identity.PlaceOfBirth = Encoding.UTF8.GetString(buffer);
                                break;
                            case 12:
                                Identity.DateOfBirth = Encoding.UTF8.GetString(buffer);
                                break;
                            case 13:
                                Identity.Gender = Encoding.UTF8.GetString(buffer);
                                break;
                        }
                    }

                    int addressFileSize = int.Parse(httpRequest.Headers["X-AppletProtocol-AddressFileSize"]);
                    byte[] addressFile = new byte[addressFileSize];
                    stream.Read(addressFile, 0, addressFileSize);
                    idx = 0;
                    while (idx < addressFileSize - 1)
                    {
                        int tag = addressFile[idx++];
                        int length = addressFile[idx++];
                        byte[] buffer = new byte[length];
                        Array.Copy(addressFile, idx, buffer, 0, length);
                        idx += length;
                        switch (tag)
                        {
                            case 1:
                                Identity.Address = Encoding.UTF8.GetString(buffer);
                                break;
                            case 2:
                                Identity.PostalCode = Encoding.UTF8.GetString(buffer);
                                break;
                            case 3:
                                Identity.Locality = Encoding.UTF8.GetString(buffer);
                                break;
                        }
                    }
                    Identity.Identified = Identity.NationalNumber != "";

                    int photoFileSize = int.Parse(httpRequest.Headers["X-AppletProtocol-PhotoFileSize"]);
                    byte[] photoFile = new byte[photoFileSize];
                    stream.Read(photoFile, 0, photoFileSize);
                    sendCommand("FinishedMessage", httpResponse);
                    return;
                }
                else
                {
                    httpResponse.StatusCode = 400; // bad request
                    return;
                }
            }
            catch 
            {
                httpResponse.StatusCode = 400; // bad request
            }
        }
        public bool IsReusable
        {
            get
            {
                return true;
            }
        }
        private void sendCommand(string command, HttpResponse httpResponse)
        {
            httpResponse.AddHeader("X-AppletProtocol-Version", "1");
            httpResponse.AddHeader("X-AppletProtocol-Type", command);
        }
    }
}
